"use strict";

function CBaseAct( owner ) {
	this.objName = "CBaseAct: ";
	
	this.owner = owner;
	this.step = 1; 
	this.nth = -1;
	this.actionSeq = new CActionSeq();

	this.initialize();
};		



	
CBaseAct.prototype = {

	initialize: function() {
		this.tradeinfo = {};
	
	},
	
	stop: function() {
			this.force_stop  = true;
	},
	resume: function() {
			this.force_stop  = false;
	},


	doTask: function( task ) {
		
			// end subs 
		if ( task == undefined ) {
			// finish... set stamp ... 
			clearInterval( this.step1.cit_timer );
			this.view.showCurIng(this.step,  'Step:' + this.step + ' Sub:' + this.subs + ' Done!');

			this.subs ++; this.nth = -1;
			
			 // done all step  1 sub seq.. go to step 3 
		 	 if( this.subs >= this.taskSeq.length ) {
		 	 	this.step = 3;
		 	 }
		 	 
			this.stampState();
			
			//  go next user action 
			this.dfd.resolve();
			return;
		} 
		
		if ( task && task.fn ) {
			debug.log(this, '\n\n ============= Cur Do task:', task.name, task.retry, task.param);
			
			// em.util.print_result( 'INITQ: ' + task.name + ' : Start == s:n ' + this.step + ':' + this.nth);
			this.view.showCurIng(this.step, task);
			
			// task.fn.apply(this, [ task, task.param , this.doNext]);
			this[task.fn].apply(this, [ task, task.param , this.doNext]);
		} else {
			debug.log ( this, 'ERROR INVLAID TASK !!!');
					//  go next user action 
			this.dfd.resolve();
		}
	},
	
	// recv result from prev task 
	// check  task entity 
	// sucess / fail check 
	//  retry? or skip 
	// wait complete ? -> set interval .  check cd list 
	//    when  cd is end - > re enter this. 
	// do next 
	doNext : function(task, result) {
		var self = this; 
		
		if (!task) {
			debug.log( this, 'No Task... specified.. : return');
			return;
		}
		
		// check  task entity
			// noti ui cur state 
		debug.log(this, ' 	Done task:', task.name, task.retry);
		debug.log(this, ' 	task Result :', result.succ ,  result);
		debug.log(this, ' 				Done task: \n', task.name, task.retry);
		// debug.log(this, ' Done task: \n\n\n ', task.name, task.retry);
		debug.log(this,  'INITQ: ' + task.name + ' : ' + (result.succ == true ? 'Succ' : 'Fail') );
		
		// noty view 
		this.view.showCurIng(this.step, task, result);
		
		if ( result.succ ) {
			// stamp state 
			this.stampState( task);
				// just do next
				var task = this.getNextTask(); 
				setTimeout( function() { self.doTask( task ); }, CUtil.RandTime(500) ); 
		 
		} else {
			// critical falit : 
			// 		stop seq.  set stamp ;  to restart next enter. 
			if ( task.fault_action == 'abort' ) {
				// alert( '############################  Task is Failed.. Critical !' + task.name);
				this.view.showCurIng(this.step, task.name + 'ERR:Abort!');
				this.dfd.resolve();
				return;
			} 
			
			//  when fail.. go next !! or stop !!.  
			else {
				debug.log(this, '\n \t ************ Error in action ', task , ' just go next act '); 
				// just do next
				// self.doTask( this.getNextTask() );
				setTimeout( function() { self.doTask( self.getNextTask() ); }, 1000 );
			}
		}
	},
	

	
	
	
	checkAllyTkSold: function  ( step,  cb ) {
		var res  = em.cstlmgr.getCurCstl().res;
		debug.log( this, ' checkAllyTkSold,  IN  step :', step, ' new G: ',  res.g);
		
		// first check : just store.. res 
		if ( ! this.prev_res ) {
			// deep copy 
			this.prev_res = {};
			$.extend( this.prev_res , res);
			return;
		}
		
		debug.log( this, ' checkAllyTkSold,  this.prev_res.g :', this.prev_res.g, ' new G: ',  res.g);
		if( step >= 2 &&  res.g > this.prev_res.g + 100000) {
				debug.log( this, ' Gotcha . TK is sold ,  IN  step :', step, ' new G: ',  res.g);
				cb ( ) ;
		}
		// this.prev_res = res;
		// deep copy 
		$.extend( this.prev_res , res);
	},
	
	/*
		 step 3  -------------------------
	*/
	
	__STEP3___BEGIN______: function() {},
	
	step3Monitor: function() {
		var outer = this;
		var self = this;
		var cstlinfo = em.cstlmgr.getCurCstl();
		
		debug.log ( this, ' step3Monitor ::', this.step3 );
		
		// force stop 
		// if ( this.force_stop ) return; 


		var actions = {
			name: 'step3',
			context: this, 
			action_table: [


			// check Gl 
				{ 
					cmd: 'check G',
					doParam: {  },
					cb : function(data) {
							debug.log ( self, 'check G ::', data ); 	
							if ( typeof data === 'object' &&  data.code == 0 ) {
								debug.log ( self, 'check G :: Success ~~~~~~~~~~~', data );
							}
							setTimeout( function() { outer.actionSeq.next.call(outer.actionSeq); } ,CUtil.RandTime(2000)); 
						},
					doFunc:	 self.checkG,
				},	
				
			// try bld 
				{ 
					cmd: 'Try_bld',
					doParam: { },  
					cb : function(data) {
									debug.log ( self, ' Try bld ::', data );
									
									// space in bld slot : try more 
									if ( data.code == 0  && data.slot < 3 ) {
										outer.actionSeq.retryCurAction('Try_bld');
									} 	
									setTimeout( function() { outer.actionSeq.next.call(outer.actionSeq); } ,CUtil.RandTime(2000)); 
					},
					doFunc:	 self.tryBld,
				},	
				// try train  : to use h first 
				{ 
					cmd: 'Try Train',
					doParam: { 'type': 2, 'num': 5000 } , 	// disband all  
					cb : function(data) {
									debug.log ( self, ' Try Train ::', data ); 
									setTimeout( function() { outer.actionSeq.next.call(outer.actionSeq); } ,CUtil.RandTime(2000)); 
						},
					doFunc:	 self.tryTrain,
				},					
			// try study
				{ 
					cmd: 'Try study',
					doParam: { },
					cb : function(data) {
									setTimeout( function() { outer.actionSeq.next.call(outer.actionSeq); } ,CUtil.RandTime(2000)); 
									debug.log ( self, ' Try study ::', data ); 	
						},
					doFunc:	 self.tryStudy,
				},	

				],
				done_cb:function () { 
					// done step3 .. 
					// clear time 
					clearInterval( self.step3.cit_timer );
					
					// noty view 
					self.view.showCurIng( self.step, 'Seq Done:T last ' + self.curTrainNum );
						
					//  go next user action 
						self.dfd.resolve();
							// restart this action seq after some time. 
							// setTimeout( function() { self.step3Monitor.call( self ); } , this.cit_timeout + 5000 ); // 1 min later 
					 },			// cb for complete action  	
		};
	
	
	
		var userinfo = CDB.getCurUserInfo();
		if ( userinfo.grade >= 30 ){
			// remove others except  donate & check G 
			actions.action_table.splice(1, actions.action_table.length-1);
			// actions.action_table.push(
			actions.action_table.unshift(
							// try donate 
				{ 
					cmd: 'Try donate',
					doParam: { },
					cb : function(data) {
									debug.log ( self, ' Try donate ::', data ); 	
									setTimeout( function() { outer.actionSeq.next.call(outer.actionSeq); } ,CUtil.RandTime(2000)); 
						},
					doFunc:	 self.tryDonate,
				}	
				 ); 
		}

	
		this.actionSeq.setAction(actions);
		this.actionSeq.start();
	},
	
	// check possible  
	// disband
	// train 
	tryTrain: function(aparam, cb) {
		var self = this;
		// noty view 
		this.view.showCurIng( this.step, 'tryTrain..:last ' + self.curTrainNum );	
		
		var cstlinfo = em.cstlmgr.getCurCstl();
		// var barr_lv = cstl.city[ CDB.BUILD.BAR.pos ];
		var barr_lv = cstlinfo.getBldLv ( CDB.BUILD.BAR) ;
		
		var ef_lv = cstlinfo.getStudyLv ( CDB.STUDY.EFF_TRAINING ) ;

		debug.log( this, ' tryTrain ::', barr_lv, ef_lv, cstlinfo, em.tasks);

		// check possible  : ef > 0 , bar > 2  : 
		// XXX:  not train when ef is  0 !!!!  ineffective 
		// if ( barr_lv < 3 ||  ef_lv < 1) {
		if ( barr_lv < 3 ||   cstlinfo.getStudyLv ( CDB.STUDY.SCOUTING ) < 1 ) {
			debug.log( this, ' Can t  train Sp  low barr, or not study scout..... ', barr_lv );
			cb(-1);
			return;
		}
		
		//	check cd list if training..
		// var cstlinfo = em.cstlmgr.getCurCstl();  
		cstlinfo.clearExpired (CDB.CDS.TRAIN );
		var ings = cstlinfo.findCdTypes (CDB.CDS.TRAIN );
		if ( ings.length >= 1 ) {
			debug.log( this, ' Train is doing...');
			cb(-1);
			return;
		}
		
		// noty view 
		this.view.showCurIng( this.step, 'Disbanding...');
			
	  // disband : update cur sol state : check max num
	  var trs  = { s: aparam.num , type: aparam.type, num: aparam.num }; // max 50000  : all spy disband 
	  em.tasks.disbandSols (trs, function(result) {
	  		if ( result && result.code != 0 ) {
	  			debug.log ( self, ' ERROR in disband!!', result);
	  		}
	  		// do train   --  don t care disban result.. 
	  		spTrain();
	  } ); 
	  
		// train  after disband 
		function spTrain() {
			debug.log(self, 'spTrain');
			
			// noty view  : 
			var userinfo = CDB.getCurUserInfo();
			self.curTrainNum = ( ef_lv *  7	 * userinfo.grade  + 90);
			self.view.showCurIng( self.step, 'Training...' +  self.curTrainNum );
			
			var trs  = {type : 2 , num : self.curTrainNum };	
			// calc res  : compare to cstl res 
			var res  = em.cstlmgr.getCurCstl().res;
			
			// calulate resorece !!!
			var per_res =  CDB.SOLS.COST[trs.type];
			var cost = {};
			$.each( Object.keys(per_res) , function (i, item) { 
				cost[item] = per_res[item] * trs.num; 
			});
			
			console.log( ' per_res ' , per_res);
			console.log( ' cost ' , cost);
			
			debug.log( this, ' build Need cost: ', cost);
	
			var calc_ret = CUtil.calcNeedRes(res, cost);
			
			em.tasks.trainSol(em.cstlmgr.getCurCstlIdx(), 
						trs,		
						// {g2f: calc_ret.exchange.f,  g2w: calc_ret.exchange.w, g2i: calc_ret.exchange.i, total:calc_ret.exchange.total } ,
						calc_ret,  
						function (data) {
							cb(data);	 
						} 
				);
		};	
		
	},	
	
	
	// check empty bld slot 
	// get bld table.  
	// check cur bld state 
	// pop done bld action
	// try next bld 
	
	// 1. check slot 
	// 2. cur blding ?  
	// N :  lv :  > curlv  ==> doBld  or skip  
	//  Y :  find next not blding WB ( wanted bld )
	// 		pop wb from tbl :  
	//			wb is blding - > push ings
	//			wb is not blding  -> do Bld  -> return
	//			reorganaze tbl :  ings + remain Tbl 
	tryBld:  function(aparam, cb) {
		
	  	// var cstlinfo = em.cstlmgr.getCurCstl();
	  	var cstlinfo = this.owner.cstlmgr.getCurCstl();
		// noty view 
		this.owner.update_view('showCurIng' ,  'tryBld ...'   );	
		  	
		// check empty bld slot
		cstlinfo.clearExpired (CDB.CDS.BLD );
		var bld_cds = cstlinfo.findCdTypes (CDB.CDS.BLD );
		if ( bld_cds.length >= 3 ) {
			debug.log( this, ' All 3 slot is blding...');
			cb(-1);
			return;
		}

		function bNowBlding (type) {
			// check current blding ?  : type, lv  both same. 
			var now_blding = bld_cds.filter ( function(el) { 
				return ( el.target == type )  ; 
				});
			return now_blding.length;
		}
			
		// get bld table.
		// [name, lv, type]  
	  	var cur_blds = cstlinfo.getBlds();
	  	// check cur bld state 
	  	while ( this.step3_bld_tbl.length !=0  ) {

	  		// get first  // [ CDB.BUILD.FAC.type, 1 ],
	  		var wb = this.step3_bld_tbl.shift() ;

			debug.log( this, 'tryBld :: cur : ', cur_blds, ' wb:', wb);
	  		// get  cur lv of wb    : cur_bld [ name, lv, type ]
	  		var cur_wb = CUtil.findElArrByValPos ( cur_blds,  wb [0]  /* bld type */ , 2 /* positoin */ );
	  		// var cur_wblv = (cur_wb !== undefined) ? cur_wb[1] : 0 ;
	  		// bld is always has value ..  in city info array   	
			
			// lv check :  cur lv > want lv : skip   
			if ( cur_wb[1] >= wb[1]  ) { // already done : cur 8,  want  8  : done..
				debug.log( this, 'tryBld :  Already Done: ', wb, cur_wb);
				continue; 
			} 
			
			if ( bNowBlding(wb[0]) ) {
				debug.log( this, ' Now Blding.. :: ', wb,  ' cur cds: ', bld_cds ,'Find Alt WB : ') ;
				
				// find not blding wb 
				var ings = [];
				
				// push back cur wb  !!!  
				ings.push(wb); 
				
				var avail_wb;
				/// pop wbs &   put  ings arr  
				while ( this.step3_bld_tbl.length !=0  ) {
						var alt_wb = this.step3_bld_tbl.shift();
						debug.log( this, ' Alt WB : ' , alt_wb) ;
						
						// get  cur lv of wb    : cur_bld [ name, lv, type ]
				  		var cur_alt_b = CUtil.findElArrByValPos ( cur_blds,  alt_wb [0]  /* bld type */ , 2 /* positoin */ );
						// lv check :  cur lv > want lv : skip   
						if ( cur_alt_b[1] >= alt_wb[1]  ) { 
							debug.log( this, 'tryBld :  Already Done: alt_wb ', alt_wb, ' cur_alt_b:', cur_alt_b);
							continue; 
						} 
						
						if ( bNowBlding(alt_wb[0]) )  {		// is blding ?
							debug.log( this, ' Is blding : push ings' , alt_wb) ; 
							// push ings 
							ings.push(alt_wb);
						}
						else {		// found aval wb : do bld
							debug.log( this, ' Found Alt WB  : Do Bld ' , alt_wb) ;  
							avail_wb = alt_wb;
							break;
						}
				}
				
				// re make bTbl 
				this.step3_bld_tbl = ings.concat(this.step3_bld_tbl);
				// do bld  if alter wb is exist 
				if ( avail_wb ) {
	  				this.conductBld ( undefined ,  {bld: avail_wb[0] , lv: avail_wb[1] -1 } , // reqres start index with 0 : need -1   
	  						function(task, result) { 
	  							if ( result.succ ) {
		  							result.slot = bld_cds.length +1 ;
	  							} else {
	  								result.slot = 3; // end :  try bld. 
	  							}
	  							cb(result); } );	
	  				
	  				return;	// cb is called.. return 
				}

				// exit while loop when no op 
  				break;
				
			} else {

				debug.log( this, 'tryBld :  do Build ~~~~~~~~~~~~~~~~~ : ', wb, cur_wb);
				
				// do bld 
  				this.conductBld ( undefined ,  {bld: wb[0] , lv: wb[1] -1 } , // reqres start index with 0 : need -1   
  						function(task, result) {
	  							if ( result.succ ) {
		  							result.slot = bld_cds.length +1 ;
	  							} else {
	  								result.slot = 3; // end :  try bld. 
	  							}
 
  							cb(result); } );	
  				
				return;		
			}
			
	  	} // while 
	  	
	  	cb(-1);
	},
	
	// check empty bld slot 
	// get bld table.  
	// check cur bld state 
	// pop done bld action
	// try next bld 
	tryStudy:  function(aparam, cb) {
	  	var cstlinfo = em.cstlmgr.getCurCstl();
	  	
		// noty view 
		this.view.showCurIng( this.step, 'tryStudy ...'   );	
		
		// check empty study  slot
		cstlinfo.clearExpired (CDB.CDS.STUDY );
		var ings = cstlinfo.findCdTypes (CDB.CDS.STUDY );
		if ( ings.length >= 1 ) {
			debug.log( this, ' All study slot is doing...');
			cb(-1);
			return;
		}

		// get studies 
	  	var cur_state = cstlinfo.studies;
	  	// check cur sty state 
	  	var o_tbl = this.step3_study_tbl;
	  	while ( o_tbl.length !=0  ) {

	  		// get first 
	  		var act = o_tbl.shift() ;
	  		debug.log( this, 'tryStudy :: act: ', act);

	  		// find  entity type  in  cur tbl  [ type, lv, possible]
	  		// got :  [[1,1,1],[2,1,1],[3,0,1]],"ext":[4,4]}; 
	  		var entity = CUtil.findElArrByValPos ( cur_state,  act [0]  /* entity type */ , 0 /* positoin */ );	
	  		debug.log( this, 'tryStudy :: cur_sty : ', entity);
			 
			// if no entity :  <- unable to study due to uni lv 
			if ( entity === undefined ) {
				debug.log( this, 'Unable Study due to Uni Lv ', act);
				o_tbl.unshift( act ) ; // back 
				
				// check low sty is done ??
				if ( act[0] >= 2 ) {
					act[0] = act[0] -1;		// type : seq..
					act[1] = 1;				// lv
					var below_act = CUtil.findElArrByValPos ( cur_state,  act [0]  /* entity type */ , 0 /* positoin */ );
					//below sty is also not done : try below sty 
					if ( ! below_act ) {
						o_tbl.unshift( act ) ; //  try low  sty  
						continue;
					}
				} 
				// eixt loop : will call cb(-1); : try when next seq. 
				break;
			}
			 
	  		// check already done or need 
	  		if (  entity && entity[1] /* cur lv */  >= act[1] /* want lv */)	{ // lv [1] 
	  			// already done : skip  & remove this.  
	  			continue;
	  		} else {
				// noty view 
				this.view.showCurIng( this.step, 'Stying ...' + act[0] + ', l:' + act[1]  );	  	
						
	  			// need to entity : do  :  when  not exist this study or less   
	  			this.conductStudy ( undefined ,  {tech: act[0] , lv: act[1] -1 } , //   cur lv : want lv - 1 
	  						function(task, result) {
	  							// fail : retry :::   
	  							if ( ! result.succ ) {
	  								o_tbl.unshift( act ) ; // back 
	  								debug.log( self, ' Study Fail::: retry !!')
	  							} 
	  							cb(result); } );	
	  			
	  			// already cb called 
	  			return;
	  		} 
	  	} // while
	  	
	  	cb(-1);
	},
	
	
	// check cur res.g 
	// if g < 200000 :  buy ally tk  & reg trade 
/*
	*******************
* Check G :
*  
*   - find tradelit,  will, trade list : 
*      ==  exist : w no check G
* 
*  - if can find mytem in tradelist 
*  		:skip buy 
* 
*   - if find my tem in  will /trade list
*   	: skip trade  
* 
*/	
	checkG:  function(aparam, cb) {
		var self = this;
			// noty view 
		this.view.showCurIng( this.step, 'checkG ...'   );	
		
		if ( this.step != 3 ) {
			debug.log(this, ' INvalid step .. .not here CheckG');
			cb(-1);
			return;
		}
		
		var cstlinfo = em.cstlmgr.getCurCstl();
	 	var g = cstlinfo.res.g;		

	  	// check when no trade info  ::  only  first enter 
	  	if (  ! self.step3.tradeinfo.status   ) {
				CheckTradeTem();
	  	} 
		//  check G : less ->  check 
		else if ( g < 600000 ) {
	  		CheckTradeTem();
	  	}  
	  // update view with cur info  
	  //  -- no need to update view...  : no change... 1!! 
	  else  {
	  		// Enough  exit.. 
	  		self.step3.tradeinfo.status = 'Enough';
			this.view.showTradeStatus ( self.step3.tradeinfo );
			cb(-1);
/*
		  this.tradeinfo.id =  self.tem_id;	  // <- set with.. tem id 
		  	// status : icon type ,  result : wattime.   id: 
			this.view.showTradeStatus (this.tradeinfo);*/

	  }


	


	
	
		// 1 st  fn for checking. 
			// Get info from trade list 
			// data.ctx_xxx <- list
			// check g eoung  .>> return after set info & update view 
		function CheckTradeTem () {
			
			// noty view 
			self.view.showCurIng( self.step, 'Check Trade...');
			
			// clear prev trade info
			self.step3.tradeinfo = {};
			
				em.tasks.checkTrade ( self.tem_id , // when buy : id is sid 
		  			function (check_data) {
	  					debug.log( self, ' Result checkTrade  in Step3: ', check_data);
	  					
		  				if( check_data.code != 0 ) { 
		  					debug.log( self, ' ~################ ERROR in checkTrade  Ally TK in step 3 ') ;
		  					cb(-1);
		  					/// stop 
		  					return;
		  				}
		  				
		  				// update view : trade info with  ,  wait , up  
		  				if (  check_data.willlist.found || check_data.mytradelist.found){
		  					self.notifyTradeInfo(check_data);
	/*
								  if ( check_data.willlist.found ) {
											self.tradeinfo.status = 'Wait Trade';
											self.tradeinfo.remainsec =  check_data.willlist.remainsec ;
											self.tradeinfo.price  =  check_data.willlist.price ;
									  } 
									  if ( check_data.mytradelist.found  ) {
											self.tradeinfo.status = 'TradingUP';
											self.tradeinfo.remainsec =  0;
											self.tradeinfo.price =  check_data.mytradelist.price;
									  }
								  self.tradeinfo.id =  self.tem_id;	  // <- set with.. tem id 
									  // status : icon type ,  result : wattime.   id: 
									this.view.showTradeStatus (tradeinfo);*/
	
								cb(check_data);
								// stop  
								return;
		  				}
							
						// if less g : then try  trade 
						if ( g < 600000 ) {
				  				if ( ! check_data.mylist.found ) {
				  						// try buy
				  							// noty view 
											self.view.showCurIng( self.step, 'Buy Tem ...'   + self.tem_id);	
											
									  		em.tasks.buyItem ( self.tem_type , self.tem_id , // when buy : id is sid 
									  			function (data) {
									  					debug.log( self, ' Result Buy Tem in Step3: ', data);
										  				if( data.code != 0 ) { 
										  					debug.log( self, 'ERROR in buy  Ally TK in step 3 : no Money??? ') ;
										  					cb(-1);
										  					/// stop 
										  					return;
										  				}
										  				
									  				// try trade 
													checkG_tryTrade (check_data);
									  			}); 
				  				} else {
					  				// try trade 
									checkG_tryTrade (check_data);
				  				}
						} 
						// first enter : check ok & m enough.
						else {
									self.step3.tradeinfo.status = 'Enough';
									self.notifyTradeInfo(check_data);
									cb(check_data);
						}
		  			} // check trade cb 
		  	);
		};
	 
	 		function checkG_tryTrade( check_data ) {
				
				// *   - if find my tem in  will /trade list
				// *   	: skip trade
  				if ( ! check_data.willlist.found &&  ! check_data.mytradelist.found )
  				{
		  			// adjust price : res.g is up-to-date ??? 
		  			// when enter startStep : always update cit info !!!  
		  			var price = self.tem_step3_price;
		  			
		  			if ( cstlinfo.res.g < self.tem_step3_price / 10 ) {
			  			var avail_g = (cstlinfo.res.g > 30000) ? (cstlinfo.res.g - 10000) : cstlinfo.res.g ;

		  				price =  Math.floor ( avail_g *10 / 10000) * 10000  + 11; // xx0089
		  				debug.log( self, ' Less Money::: Adjust new price!! : ' , self.tem_step3_price);
		  			}
		  			
		  			// do trade  ------
					// noty view 
					self.view.showCurIng( self.step, 'Reg Trade ...'   + price);	
	  				 em.tasks.tradeReg (  self.tem_id, 0,  1, price, 
		  					function(data) {
			  						if( data.code != 0 ) { debug.log( self, 'ERROR in Trade Reg Ally TK in step 3 ') ;}
			  						else {
				  						self.step3.tradeinfo.status = 'TradingUP';
			  							debug.log( self, ' SUccess Trade Up!!! ', self.tem_id , price );
			  							debug.log( self, ' Cur Time :  ', CUtil.TimeToString(new Date() ) );
			  							self.notifyTradeInfo( data );
			  						}
			  						cb(data);
		  					} ); 
  				} 
			};  // end fn 

	},
	
	 notifyTradeInfo : function( data ) {
	 	var self = this;
			if (  data.willlist && data.willlist.found ) {
				  self.step3.tradeinfo.status = 'Wait Trade';
				  self.step3.tradeinfo.remainsec =  data.willlist.remainsec ;
				  self.step3.tradeinfo.price  =  data.willlist.price ;
			} 
			if ( data.mytradelist && data.mytradelist.found  ) {
				  self.step3.tradeinfo.status = 'TradingUP';
				  self.step3.tradeinfo.remainsec =  0;
				  self.step3.tradeinfo.price =  data.mytradelist.price;
			}
			if ( data.mylist && data.mylist.found  ) {
				  self.step3.tradeinfo.temcnt  =  data.mylist.temcnt;
			}
		 	self.step3.tradeinfo.id =  self.tem_id;	  // <- set with.. tem id 
		  	// status : icon type ,  result : wattime.   id: 
			this.view.showTradeStatus ( self.step3.tradeinfo );
	},
	
	tryDonate:  function(aparam, cb) {
		var self = this;
		
		var u_info = CDB.getCurUserInfo();
		
		// check subscribed state
		if ( ! u_info.guild  && ! self.applyAlly ) {
				// try apply 
				em.tasks.applyAlly( function(data) {
					if ( data.code == 0 ) {
						debug.log( self, 'Apply Ally OK !!! \n\n\n');
						// noti view 
						self.view.informAllyState ('Apply Done');
					}
					cb(0);
				});
				self.applyAlly = true;
				return;
		}
		
		debug.log( self, ' Gld : ', u_info.guild );
		
		var cstlinfo = em.cstlmgr.getCurCstl();
	 	var donate_g = cstlinfo.res.g - 100000;	
	 	if ( donate_g <= 0)  {
	 			this.view.informAllyState ('not enough G !!' );
				cb(0);
				return;
	 	}
	 	var tech_o_ar = [ [1,30000] , [6,75000], [5,75000] ,   [11,200000], [10,200000] ];
	 	
		// check subscribed status & get cool time
		// try donate with all remain g   
		em.tasks.donate( donate_g,  tech_o_ar, function(data) {
			// if cool remains return. 
			debug.log(self, 'tryDonate' ,  data);
			
			if ( data.code == -1 ) {
				debug.log( self, ' Not Yet joined.... \n\n');
				cb(0);
				return;
			}
			
			// remains cool 
			if ( data.code == 1 ) {
				// noty view : cool 
				debug.log ( self, 'Cool time : ', data.hall_cool );
				
				this.view.informAllyState ('Cool', data.hall_cool);
				cb(0);
				return;
			}
			
			if ( data.code == 100) {
				// only hall is avlable	
				debug.log ( self, 'Only Hall Done !! : ', data.hall_domax );
			}


		this.view.informAllyState ('Donate Done' + data.hall_domax );
		debug.log(self, 'Done!!! donate ');
		cb(0);
		}) ;
		
	},
	
	// ================================================ 
	// each  task    
	
	
	___EACH_FUNCTION_DEFINE______: function() {} ,
	// 1 shot task :  use ahelper  : direct cb 
	getGift: function( task,  code, cb ) {
		
		var self = this;
		debug.log(this, 'this', this, task);
		// use action helper
	 	var username = CDB.getCurUser();
		var param = { 'user': username, 'code': code,  
				cb : function (data) {
						// succ/ fail check 
						data.succ = true;
						if ( data.code != 0 ) data.succ = false;
						if( cb) {	cb.apply (self, [ task, data ]);	}	  
					} 
				};
		em.ahelper.gift(param);		
	},
		/*
			GET /game/get_userinfo_api.php?jsonpcallback=jsonp1326014287292&_=1326016300674&key=0314fac3e037989c062370584d3dc99b&_l=en&_p=EW-DROID HTTP/1.1

		*/
	getUserInfo:  function( task,  param ,cb ) {
		
		var self = this;
		debug.log(this, 'this', this, task);
		// use action helper
		var param = { 
				cb : function (data) {
						// succ/ fail check 
						data.succ = true;
						if ( data.code != 0 ) data.succ = false;
						if( cb) {	cb.apply (self, [ task, data ]);	}	  
					} 
				};
		em.ahelper.get_userinfo_api(param);		
	},
	trainSol:  function( task,  param , cb) {
		
		var self = this;
		debug.log(this, 'this', this, task);
// 'sol_type': 1, 'sol_num': 10

		// calc res  : compare to cstl res 
		var trs = param.trs;
		// calulate resorece !!!
		var per_res =  CDB.SOLS.COST[trs.type];
		var cost = {};
		$.each( Object.keys(per_res) , function (i, item) { 
			cost[item] = per_res[item] * trs.num; 
		});
		
		var calc_ret = CUtil.calcNeedRes(em.cstlmgr.getCurCstl().res, cost);

		em.tasks.trainSol(em.cstlmgr.getCurCstlIdx(), 
					trs,
					calc_ret ,  // exchange res 
					function (data) {
						// succ/ fail check
						if ( data.code == 0 ) {
							data.succ = true;
							// move cstl to update new res 
							var cb_cstlmove ;
							em.cbs.cstlmove1done.add( cb_cstlmove = function () { 
							em.cbs.cstlmove1done.remove( cb_cstlmove);
							if( cb) {	cb.apply (self, [ task, data ]);	}	 
							}  ); 
							
							em.cstlmgr.moveCstlAt( em.cstlmgr.getCurCstlIdx() );
						} else {
							data.succ = false;	
							debug.log( self, ' TRain Fail... ', data);
							if( cb) {	cb.apply (self, [ task, data ]);	}	  
						}
					} 
					);
	},
	
	buyGemItem:  function( task,  param , cb) {
		var self = this;
		debug.log(this, 'this', this, task);

		em.tasks.buyGemItem(	 param.cat , param.id ,
					function (data) {
						// succ/ fail check 
						data.succ = true;
						if ( data.code != 0 ) data.succ = false;
						if( cb) {	cb.apply (self, [ task, data ]);	}	 	 
					} 
					);
	},
	
	hireH:  function( task,  param , cb) {
		
		var self = this;
		debug.log(this, 'this', this, task);

		em.tasks.hireH( 
					function (data) {
						// succ/ fail check 
						data.succ = true;
						if ( data.code != 0 ) data.succ = false;
						if( cb) {	cb.apply (self, [ task, data ]);	}	 	 
					} 
					);
	},
	
							
	// use dfd . tasks : when  		
	// if task == undefined.  do not go next 
	conductBld	: function( task,  param , cb ) {
		var self = this;
		
		var type;
		if ( typeof param.bld === 'number') {
			 type= param.bld;
		} else {
			 type= param.bld.type;
		}
		var lv = param.lv ;
		
		var cstlinfo = em.cstlmgr.getCurCstl();
		var cur_lv  = cstlinfo.getBldLv ( param.bld  ) ;

		debug.log( this, ' param: type ', type, 'lv:', lv , ' CurLv', cur_lv);
		// !! caution :  param.lv is not want lv. : cur lv..
		if ( cur_lv >  param.lv ) {
			// already done .. skip
			if( cb) {	cb.apply (self, [ task,  {succ: false } ] );	}	 			
			return;
		}
				
		var dfd = $.Deferred();

		// noty view 
		this.view.showCurIng( this.step, 'Blding ...' + type + ', l:' + param.lv );
		// only success
		$.when(dfd).then( function(result) {
			//	{"code":0,"ret":{
// 			// "cdlist":[{"id":847443,"cdtype":1,"target":"8","owner":0,"secs":521}]}})
						debug.log(self, 'ret BUILD Success!!', result);
						if ( result.code == 0 ) result.succ = true;
						
						// move cstl to update new res 
						var cb_cstlmove ;
						em.cbs.cstlmove1done.add( cb_cstlmove = function () { 
						em.cbs.cstlmove1done.remove( cb_cstlmove);
						if( cb) {	cb.apply (self, [ task, result ]);	}	 
						}  ); 
						
						em.cstlmgr.moveCstlAt( em.cstlmgr.getCurCstlIdx() );
						
						// if( cb) {	cb.apply (self, [ task, result ]);	}	 
					}
					, function(result) {
						var error_str = '';
						if( result.code == 704 ) error_str = 'no slot for bld: need bless of bld'; 
						if( result.code == 708 ) error_str = 'Need more Res.. check !!'; 
						//alert('build fail :' + result.code + error_str);
						result.succ = false;
						if( cb) {	cb.apply (self, [ task, result ]);	}	 
					}
		);


		
		// calc res  : compare to cstl res 
		var res  = em.cstlmgr.getCurCstl().res;
		// remain minimum f : 
		var cost = CDB.getBuildRes(type, lv) ;	
		//cost.f += CDB.getCurUserInfo().MinFood;
		debug.log( this, ' build Need cost: ', cost);


		var calc_ret = {} ;
		if ( ! cost ) {	// no info build cost : not important.. just build 
			calc_ret =  {'possible': true, 'exchange': {f:0, w:0, i:0 , total: 0 } };			
		}  else {
			calc_ret = CUtil.calcNeedRes(res, cost);
		}

		em.tasks.doBuild( dfd, type, {g2f: calc_ret.exchange.f,  g2w: calc_ret.exchange.w, g2i: calc_ret.exchange.i, total:calc_ret.exchange.total }  );
		
	},		
		
	// use dfd . tasks : when  		
	conductStudy	: function( task,  param , cb ) {
		var self = this;
	
		debug.log(this, 'conductStudy ', param);
		
		// calc res  : compare to cstl res 
		var res  = em.cstlmgr.getCurCstl().res;
		var cost = CDB.getStudyRes( param.tech, param.lv) ;	
		debug.log( this, ' getStudyRes Need cost: ',  cost , 'cur res: ', res);
		var calc_ret = CUtil.calcNeedRes(res, cost);

		// check possible 
		if ( ! calc_ret.possible  ) {
				// update status ... 
			debug.log(this, 'Not Enough Res!!  IN conductStudy  ' );
			if( cb) {	cb.apply (self, [ task, {succ:false} ]);	}
			return;
		}
		
		var dfd = $.Deferred();

		// OK : COLOR -> YELLOW
		// result - > cd list  update to cstlmgr by tasks 
		function processRet(result) {
				debug.log( self, 'conductStudy : result ', result);
				if (result.code == 0 && result.ret && result.ret.cdlist ) {
					result.succ = true;
					debug.log(self, 'ret Sutdy Success!!', result);
				
					// move cstl to update new res
					var cb_cstlmove ;
					em.cbs.cstlmove1done.add( cb_cstlmove = function () { 
						em.cbs.cstlmove1done.remove( cb_cstlmove);
						if( cb) {	cb.apply (self, [ task, result ]);	}	 
						}  ); 

					em.cstlmgr.moveCstlAt( em.cstlmgr.getCurCstlIdx() );

				} else {
					result.succ = false;
					debug.log( self, 'conductStudy : FAIL ', result );
					if( cb) {	cb.apply (self, [ task, result ]);	}	 
				}


		};	
		
		// only success
		$.when(dfd).then( processRet, processRet );


		em.tasks.doStudy( dfd, param.tech, 
				{g2f: calc_ret.exchange.f,  g2w: calc_ret.exchange.w, g2i: calc_ret.exchange.i, total:calc_ret.exchange.total }  );
							
	},			
				
	fastActionTem : function( task,  param , cb ) {
		var self = this;
		var type  = param.type ;	
	
		debug.log(this, 'fastActionTem  ::: ', type , param );
		// type, fastid, cdtype, target  , done_cb 
		em.tasks.fastActionTem ( type , param.sid, param.cdtype, param.target,  
					function (data) {
						// succ/ fail check 
						if ( data.code == 0 )			data.succ = true;
						
						debug.log( self, ' FAST ================ \n\n RET \t\t ', data , 'cdid ', data.cdid );
						// update cd list when secs : 0 
						// "code":0,"ret":{"secs":0}}
						if ( data.cdid ) {
							var ret_cd = [ {"id": data.cdid,"cdtype": type,"target":param.target,"owner":0,"secs": data.secs}];
							debug.log( self, ' FAST ================ \n\n UPDATE CDLIST \t\t ', ret_cd, 'cdid ', ret_cd.cdid);
							
							em.cstlmgr.updateCdlist(ret_cd);			
						}
						if( cb) {	cb.apply (self, [ task, data ]);	}	  
			}		);	
		
	},			
	// 1 shot task :   use ahelper  : direct cb 
	conductQst: function( task,  param , cb) {
		
		var self = this;
		
		function conductTask() {
			// use action helper
			var conduct_param = {   'action': param.action, 'id': param.id, 
					cb : function (data) {
						//  task_up :  "code":0,"ret":{"status":2}})
						//  task_end : {"code":0,"ret":{"quest":[{"id":48,"grade":0,"status":0,"done":0}]}})
								// {"id":46,"grade":0,"status":1,"done":0},		//  status : accepted ,  not done
	// 							 		{"id":48,"grade":0,"status":0,"done":1},		// status : 0,  done : done ...
							// succ/ fail check 
							if ( data.code == 0 ) data.succ = true;
							if( cb) {	cb.apply (self, [ task, data ]);	}	 
						} 
					};
			em.ahelper.system_task_conduct (conduct_param);
			return;		
		};
		
		// first  get task list 
		var tasklist_param = { action: 'task_list', cb : function (data) {
									debug.log( self, 'SystemTask List : ', data);
									conductTask();
									}	};
		em.ahelper.system_task_api (tasklist_param);
	},
	
	useItem: function( task,  param, cb ) {
		
		var self = this;
		
// 		GET /game/
/*

// use ref gift 

goods_api.php?jsonpcallback=jsonp1326014287249&_=1326014559916&key=0314fac3e037989c062370584d3dc99b
&action=goods_list
&type=3
&page=1
&_l=en&_p=EW-DROID HTTP/1.1


jsonp1326014287249({"code":0,"ret":{"max":1,
"item":[{"item":
{"id":75614,"sid":167,"num":1},"use":1,"sale":0},
{"item":{"id":75612,"sid":128,"num":1},"use":1,"sale":0},
{"item":{"id":75616,"sid":190,"num":1},"use":1,"sale":50000},
{"item":{"id":75609,"sid":168,"num":1},"use":1,"sale":0},
{"item":{"id":75615,"sid":188,"num":1},"use":2,"sale":0},
{"item":{"id":75611,"sid":126,"num":1},"use":1,"sale":0},
{"item":{"id":75606,"sid":169,"num":1},"use":1,"sale":0},
{"item":{"id":75613,"sid":161,"num":2},"use":1,"sale":0},
{"item":{"id":75610,"sid":80,"num":1},"use":1,"sale":0}]}})




GET /game/
goods_mod_api.php?jsonpcallback=jsonp1326014287250&_=1326014568812&key=0314fac3e037989c062370584d3dc99b
&action=use
&city=17736
&id=75614
&num=1
&_l=en&_p=EW-DROID HTTP/1.1

jsonp1326014287250({"code":0,"ret":
{"item":[],"gem":0,"buff":
{"id":6381,"itemid":167,"secs":2592000},"wood":0,"food":0,"iron":0,"gold":0}})

list one more : updtae cur page 


GET /game/goods_mod_api.php?jsonpcallback=jsonp1326014287252&_=1326014587093&key=0314fac3e037989c062370584d3dc99b
&action=use
&city=17736
&id=75606
&num=1
&_l=en&_p=EW-DROID HTTP/1.1

jsonp1326014287252({"code":0,"ret":
{"item":[
{"id":0,"sid":153,"num":1},
{"id":0,"sid":115,"num":3},
{"id":0,"sid":118,"num":3},
{"id":0,"sid":161,"num":3}],"gem":0,
"buff":"","wood":0,"food":0,"iron":0,"gold":0}})


list one more : updtae cur page 




////////////// use chest 


/// use item  : item list 
GET /game/
goods_api.php?jsonpcallback=jsonp1326014287328&_=1326017016998&key=0314fac3e037989c062370584d3dc99b
&action=goods_list
&type=3
&page=1
&_l=en&_p=EW-DROID HTTP/1.1

jsonp1326014287328({"code":0,"ret":{"max":2,"item":[{"item":{"id":75612,"sid":128,"num":1},"use":1,"sale":0},{"item":{"id":75616,"sid":190,"num":1},"use":1,"sale":50000},{"item":{"id":75609,"sid":168,"num":1},"use":1,"sale":0},{"item":{"id":75618,"sid":115,"num":3},"use":2,"sale":0},{"item":{"id":75615,"sid":188,"num":1},"use":2,"sale":0},{"item":{"id":75619,"sid":118,"num":3},"use":2,"sale":0},{"item":{"id":75611,"sid":126,"num":1},"use":1,"sale":0},{"item":{"id":75613,"sid":161,"num":2},"use":1,"sale":0},{"item":{"id":75620,"sid":161,"num":3},"use":1,"sale":0},{"item":{"id":75644,"sid":131,"num":1},"use":1,"sale":0}]}})

// use chest 
GET /game/
goods_mod_api.php?jsonpcallback=jsonp1326014287329&_=1326017033995&key=0314fac3e037989c062370584d3dc99b
&action=use
&city=17736
&id=75644
&num=1
&_l=en&_p=EW-DROID HTTP/1.1


jsonp1326014287329({"code":0,"ret":
{"item":[],"gem":0,"buff":"","wood":0,"food":0,"iron":0,
"gold":30000}})


// update 
jsonp1326014287328({"code":0,"ret":{"max":2,"item":[
{"item":{"id":75612,"sid":128,"num":1},"use":1,"sale":0},
{"item":{"id":75616,"sid":190,"num":1},"use":1,"sale":50000},
{"item":{"id":75609,"sid":168,"num":1},"use":1,"sale":0},
{"item":{"id":75618,"sid":115,"num":3},"use":2,"sale":0},
{"item":{"id":75615,"sid":188,"num":1},"use":2,"sale":0},
{"item":{"id":75619,"sid":118,"num":3},"use":2,"sale":0},
{"item":{"id":75611,"sid":126,"num":1},"use":1,"sale":0},
{"item":{"id":75613,"sid":161,"num":2},"use":1,"sale":0},
{"item":{"id":75620,"sid":161,"num":3},"use":1,"sale":0},
{"item":{"id":75644,"sid":131,"num":1},"use":1,"sale":0}]}})



*/

		em.tasks.useItem ( param.type, param.sid, param.id,  param.num, 
					function (data) {
						// succ/ fail check 
						data.succ = true;
						if ( data.code != 0 ) data.succ = false;
						if( cb) {	cb.apply (self, [ task, data ]);	}	  
					}
					);	
		
	},
/*
	sell
*/


	saleItem: function( task,  param , cb) {
		
		var self = this;
		
		em.tasks.saleItem( param.type, param.sid, param.id, param.num , 
					function (data) {
						// succ/ fail check 
						data.succ = true;
						if ( data.code != 0 ) data.succ = false;
						if( cb) {	cb.apply (self, [ task, data ]);	}	  
					}
					);	
		
	},
// buy shop  trade   item 
// ignore param. 
buyTradeItem: function( task,  param , cb ) {
		
		var self = this;
		
		em.tasks.buyItem ( this.tem_type , this.tem_id, 
					function (data) {
						// succ/ fail check 
						data.succ = true;
						
						// jsonp1326014287360({"code":0,"ret":{"gold":32708,"itemid":75656}})
						// save all token id  : for registering. 
						self.allyTokenId =  data.ret.itemid; 
						
						debug.log( this, '\t\t BUY TEM  : ID  : ', self.allyTokenId);
						
						if ( data.code != 0 ) data.succ = false;
						if( cb) {	cb.apply (self, [ task, data ]);	}	  
					}
					);	
		
	},

	// ignore param. 
	tradeReg: function( task,  param ,cb ) {
		
		var self = this;
		
		var trade_id  = self.allyTokenId;
		// debug.log( this, ' \t\t Trade Reg : ', param);
		debug.log( this, ' \t\t Trade Reg :: TEM.ID : ', this.tem_sid);
		
		var price = self.tem_price;
		var cstlinfo = em.cstlmgr.getCurCstl();
		if ( cstlinfo.res.g < price / 10 ) {
			price =  Math.floor ( (cstlinfo.res.g - 1000 ) *10 / 10000) * 10000  + 11; // xx0089
			debug.log( self, ' Less Money::: Adjust new price!! : ' , price);
		}
		// em.tasks.tradeReg (  param.sid, param.id,  param.num, param.price, 
		em.tasks.tradeReg (  this.tem_sid, trade_id,  1, price, 
					function (data) {
						// succ/ fail check
						
						// when succ 
						// {"code":0,"ret":{"item":[[2756,113,310089,832]],"max":1}}) 
						if ( data.code == 0 ) {
							data.succ = true;
  							// debug.log( self, ' SUccess Trade Up!!! ', param.sid, param.id,  param.num, param.price );
  							debug.log( self, ' SUccess Trade Up!!! ', self.tem_sid, trade_id,  1, self.tem_price );
  							debug.log( self, ' Cur Time :  ', CUtil.TimeToString(new Date() ) );							
						}
						if( cb) {	cb.apply (self, [ task, data ]);	}	  
					}
					);	
		
	},

	// ignore param 
	checkTrade: function( task,  param ,cb ) {
		var self = this;
		debug.log( this, ' \t\t checkTrade Reg :: TEM.ID : ',  this.tem_id );
		
			em.tasks.checkTrade ( this.tem_id , // when check with sid  
		  			function (check_data) {
	  					debug.log( self, ' Result checkTrade  in Step3: ', check_data);
		  				if( check_data.code != 0 ) { 
		  					debug.log( self, 'ERROR in checkTrade  Ally TK in step  ', self.step ) ;
		  					check_data.succ = false;
		  				} else {
		  					self.notifyTradeInfo(check_data);
			  				if (  check_data.willlist.found || check_data.mytradelist.found){
			  					debug.log( self, 'ERROR in checkTrade  Ally TK in step  ', self.step ) ;
			  					// 0em.util.print_result( '\n\n Trade tem is On the List  \n\n\n <br/>' + CUtil.SecToString( check_data.willlist.remainsec) );	 
			  					// em.util.print_result( '<br/> UP Time :  ' + CUtil.TimeToString( new Date( $.now() + check_data.willlist.remainsec * 1000) ) ); 
			  				}
			  				check_data.succ = true;
		  				}
						if( cb) {	cb.apply (self, [ task, check_data ]);	}		  				
		  			}
		  			);
	},
/*
	GET /game/
	goods_mod_api.php?jsonpcallback=jsonp1326014287254&_=1326014610596&key=0314fac3e037989c062370584d3dc99b
	&action=sale
	&city=17736
	&id=75616
	&_l=en&_p=EW-DROID HTTP/1.1

*/
	// 1 shot task :   use ahelper  : direct cb 
	checkCd: function( task,  param , cb ) {
		var self = this;
		
		// timer 
		function  checkCdTimeFn() {
			// get cd type
			// finish check ?   
			// ok - remove cd . 
			// go next : 
				debug.log(self, ' checkCdTimeFn for task completion :');
					// check cdlist
					
					var bCompleted =  em.cstlmgr.bCompleteCdlist(param.cdtype, param.target );
					
					debug.log(this, 'complete ? :', bCompleted);
					if (  bCompleted  ) {
						// clear this timer 
						clearTimeout( self.cd_timer);
						
						// get cd info when complete cd 
						em.tasks.getCDInfo(em.cstlmgr.curCstlID(),
							 function ( data ) {
								// send task to do next
								var data  = { succ: true};
								if( cb) {	cb.apply (self, [ task, data ]);	}	 
						});
						
					} else {
						if ( task.fault_action == 'abort') {
							var data  = { succ: false};
							if( cb) {	cb.apply (self, [ task, data ]);	}
							return;
						}
						// set next timeout 
						self.cd_timer = setTimeout( checkCdTimeFn , 10000);
					} 
			
					 
		};
		// set timer :  first   : to wait ... loop 
		this.cd_timer = setTimeout( checkCdTimeFn , 0);
	},
	
	
	// when enter seq.. res is already.  updated... 
	// do not get cit info again..!!! 
	CheckRes: function( task,  param ,cb ) {
		var self = this;
		var res  = em.cstlmgr.getCurCstl().res;
		debug.log( this, ' \t\t CheckRes res : ',  param.res , 'curRes:', res);
		
		var result = {succ: false};		
		if ( CUtil.compareRes(res, param.res) > 0 ) {
			result.succ = true;
		} 
		
		if( cb) {	cb.apply (self, [ task, result ]);	}
				
	},	
	
	
	// get cstl info..  : all infos will updated in tasks cbs.. 
	getCurCstlInfo: function( task,  param ,cb ) {
		var self = this;
		debug.log( this, ' \t\t ========== getCurCstlInfo : ' );
		
		var cstlinfo = em.cstlmgr.getCurCstl();
		
		// always success..  
		function update_cur_cstl(result) {
			result.succ = true;
			if( cb) {	cb.apply (self, [ task, result ]);	}
		};
		
		em.tasks.getCstlInfos(cstlinfo, update_cur_cstl) ; 
	},	
	
};

		